#include "fxcc/core/graph/common/GeometryData.h"

using namespace fxcc::graph::common;

void fxcc::graph::common::GeometryData::Inject(int index, VertexFixed& v) const
{
    v.pos = vertices[index];
    v.normal = normals[index];
    v.tex = texcoords[index];
    v.tangent = tangents[index];
    v.bigTangent = bigTangents[index];
};

bool GeometryData::ResizeHeader(const Header& header)
{
    vertices.resize(header.numVertcies);
    normals.resize(header.numNormals);
    texcoords.resize(header.numTexCoords);
    tangents.resize(header.numTangents);
    bigTangents.resize(header.numBigTangents);
    indices32.resize(header.numIndices);

    return true;
}

bool fxcc::graph::common::GeometryData::WriteToFile(const std::string& path) const
{
    fxcc::Base::CreateParentDirs(path);

    std::ofstream ofs(path, std::ios::binary); 

    if (!ofs.is_open())
    {
        ztclog::info("failed open file %s", path.c_str());
        return false;
    }

    Write(ofs);

    ofs.flush();
    ofs.close();
    return true;
}

void GeometryData::Write(std::ofstream& ofs) const
{
    Header header = GetHeader();

    ofs.write(reinterpret_cast<const char*>(&header), sizeof(header));

    if (!vertices.empty())
        ofs.write(reinterpret_cast<const char*>(&vertices[0]), sizeof(glm::vec3) * vertices.size());

    if (!normals.empty())
        ofs.write(reinterpret_cast<const char*>(&normals[0]), sizeof(glm::vec3) * normals.size());

    if (!texcoords.empty())
        ofs.write(reinterpret_cast<const char*>(&texcoords[0]), sizeof(glm::vec2) * texcoords.size());

    if (!tangents.empty())
        ofs.write(reinterpret_cast<const char*>(&tangents[0]), sizeof(glm::vec3) * tangents.size());

    if (!bigTangents.empty())
        ofs.write(reinterpret_cast<const char*>(&bigTangents[0]), sizeof(glm::vec3) * bigTangents.size());

    if (!indices32.empty())
        ofs.write(reinterpret_cast<const char*>(&indices32[0]), sizeof(unsigned int) * indices32.size());

}

bool fxcc::graph::common::GeometryData::ReadFromFile(const std::string& path)
{
    std::ifstream ifs(path, std::ios::binary);
    if (!ifs.is_open())
    {
        ztclog::info("failed to open file %s for reading", path.c_str());
        return false;
    }

    bool result = Read(ifs);

    ifs.close();
    return result;
}

bool fxcc::graph::common::GeometryData::Read(std::ifstream& ifs)
{
    Header header;
    ifs.read(reinterpret_cast<char*>(&header), sizeof(header));
    vertices.resize(header.numVertcies);
    normals.resize(header.numNormals);
    texcoords.resize(header.numTexCoords);
    tangents.resize(header.numTangents);
    bigTangents.resize(header.numBigTangents);
    indices32.resize(header.numIndices);

    if (!vertices.empty())
        ifs.read(reinterpret_cast<char*>(&vertices[0]), sizeof(glm::vec3) * vertices.size());

    if (!normals.empty())
        ifs.read(reinterpret_cast<char*>(&normals[0]), sizeof(glm::vec3) * normals.size());

    if (!texcoords.empty())
        ifs.read(reinterpret_cast<char*>(&texcoords[0]), sizeof(glm::vec2) * texcoords.size());

    if (!tangents.empty())
        ifs.read(reinterpret_cast<char*>(&tangents[0]), sizeof(glm::vec3) * tangents.size());

    if (!bigTangents.empty())
        ifs.read(reinterpret_cast<char*>(&bigTangents[0]), sizeof(glm::vec3) * bigTangents.size());

    if (!indices32.empty())
        ifs.read(reinterpret_cast<char*>(&indices32[0]), sizeof(unsigned int) * indices32.size());

    return true;
}

fxcc::graph::common::GeometryData::Header GeometryData::GetHeader() const
{
    Header header;
    header.numVertcies = vertices.size();
    header.numNormals = normals.size();
    header.numTexCoords = texcoords.size();
    header.numTangents = tangents.size();
    header.numBigTangents = bigTangents.size();
    header.numIndices = indices32.size();

    return header;
}
